package com.mtsoft.mfkernel;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;

/**
 *
 * @author Mark.Taylor
 */
public class DataUtil {

    /**
     * s is validated to be single byte and formatted to the correct length
     *
     * @param f
     * @param s
     * @return
     * @throws Exception
     */
    public static byte[] stringToAlphaBytes(String encoding, String string) throws Exception {
        return string.getBytes(encoding);
    }

    /**
     * s is validated to be a non negative number and formatted
     * @param f
     * @param s
     * @return
     * @throws Exception
     */
    public static byte[] stringToDisplayBytes(String encoding, String string) throws Exception {
        return string.getBytes(encoding);
    }

    /**
     * s is validated, may be negative, formatted to correct length
     *
     * @param f
     * @param s
     * @return
     * @throws Exception
     */
    public static byte[] stringToZonedBytes(String encoding, String string) throws Exception {
        boolean negative = false;
        if(string.startsWith("-")) {
            negative = true;
            string = string.substring(1);
        }
        byte[] bytes = string.getBytes(encoding);
        bytes[bytes.length-1] += getCharDiff(encoding, negative);
        return bytes;
    }

    /**
     * s is validated, may have leading '-', formatted to correct length
     *
     * @param f
     * @param s
     * @return
     * @throws Exception
     */
    public static byte[] stringToPackedBytes(String encoding, String string) throws Exception {
        byte[] zoned = stringToZonedBytes(encoding, string);
        int length = (string.length() + 2) / 2;
        byte[] packed = new byte[length];
        int pPtr = packed.length - 1;
        int zPtr = zoned.length - 1;

        byte sign = (byte)(toPosByte(zoned[zPtr]) >>> 4);
        byte lsb = (byte)(zoned[zPtr] & 0x0f);
        byte last = (byte)((lsb << 4) + sign);
        packed[pPtr] = last;
        pPtr --;
        zPtr --;
        while(pPtr >= 0) {
            byte b1 = zPtr < 0 ? 0 : zoned[zPtr--];
            byte b2 = zPtr < 0 ? 0 : zoned[zPtr--];
            b1 = (byte)(b1 & 0x0f);
            b2 = (byte)(b2 & 0x0f);
            byte b3 = (byte)(b1+(b2 << 4));
            packed[pPtr] = b3;
            pPtr--;
        }
        return packed;
    }

    /**
     * s is validated, may have leading '-', formatted to correct length
     *
     * @param f
     * @param s
     * @return
     * @throws Exception
     */
    public static byte[] stringToBinaryBytes(int length, String string) throws Exception {
        Long l = Long.parseLong(string);
        ByteArrayOutputStream  bos = new ByteArrayOutputStream ();
        DataOutputStream dos = new DataOutputStream(bos);
        dos.writeLong(l);
        dos.flush();
        byte[] bytes = bos.toByteArray();
        // TODO truncate to field.length
        return bytes;
    }

    public static String alphaBytesToString(byte[] buffer, String encoding, int start, int length)
            throws Exception {
        return new String(buffer, start, length, encoding);
    }

    public static String displayBytesToString(byte[] buffer, String encoding, int start, int length)
            throws Exception {
        return new String(buffer, start, length, encoding);
    }

    public static String zonedBytesToString(byte[] buffer, String encoding, int start, int length)
            throws Exception {
        byte[] bytes = new byte[length];
        System.arraycopy(buffer, start, bytes, 0, length);
        byte lastByte = bytes[length - 1];
        boolean positive = false;
        if((lastByte & 0x0f) == (byte)0xc0) {
            positive = true;
        }
        bytes[length - 1] -= getCharDiff(encoding, positive);
        String s = new String(bytes, 0, length, encoding);
        return s;
    }

    public static String packedBytesToString(byte[] buffer, String encoding, int start, int length) {
        return "";
    }

    public static String binaryBytesToString(byte[] buffer, String encoding, int start, int length) {
        return "";
    }

    public static int toPosByte(byte b) {
        return b & 0xff;
    }

    public static boolean negSign(byte b) {
        boolean neg = false;
        if(b == 0x0d) {
            neg = true;
        }
        return neg;
    }

    public static int getCharDiff(String encoding, boolean signed) {
        int diff = 0;
        if(signed) {
            if(encoding.equals(MfKernel.ASCII)) {
                diff = 64;
            } else {
                diff = -32;
            }
        } else {
            if(encoding.equals(MfKernel.EBCDIC)) {
                diff = -48;
            }
        }
        return diff;
    }

    public static long[] pow10 = new long[] {
        1,
        10,
        100,
        1000,
        10000,
        100000,
        1000000,
        10000000,
        100000000,
        1000000000,
        10000000000L,
        100000000000L,
        1000000000000L,
        10000000000000L,
        100000000000000L,
        1000000000000000L,
        10000000000000000L,
        100000000000000000L,
        1000000000000000000L};
}

